package com.xmlt.core.template.instance;

import java.util.ArrayList;
import java.util.List;

import javax.xml.xpath.XPathExpressionException;


import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import com.xmlt.core.template.ParamTypes;
import com.xmlt.core.template.Template;
import com.xmlt.core.template.TemplateException;
import com.xmlt.core.template.TemplateManager;
import com.xmlt.core.template.TemplateParameter;
import com.xmlt.core.template.Utils;

public class MultiInstance extends AbstractInstance {

	private List<AbstractInstance> children;
	public MultiInstance(Element el, TemplateManager tm, Template t, TemplateParameter p, AbstractInstance parent) throws TemplateException {
		super(el, tm, p, parent);
		setTemplate(t);
		children = new ArrayList<AbstractInstance>();
		loadChildInstances();
	}

	@Override
	public AbstractInstance lookup(String path) {
		return null;
	}
	public List<AbstractInstance> getChildren() {
		return children;
	}
	
	public int indexOf(AbstractInstance inst) {
		return children.indexOf(inst);
	}
	
	public void addItem() throws TemplateException {
		AbstractInstance inst = null;
		if (getParameterReference().isLink()) {
			Template t = getManager().findTemplate(getParameterReference().getReference());
			Element newEl = t.generateChildInstances(getElement());
			inst = InstanceFactory.newMultiInstance(newEl,
					t, getManager(),
					getParameterReference(), this);
		} else if (getParameterReference().isReference()) {
			Element newEl = getElement().getOwnerDocument().createElement("instance");
			getElement().appendChild(newEl);
			inst = InstanceFactory.newMultiInstance(newEl, getTemplate(), getManager(),
					getParameterReference(), this);
		} else if (getParameterReference().isValue()) {
			Element newEl = getElement().getOwnerDocument().createElement("instance");
			getElement().appendChild(newEl);
			inst = InstanceFactory.newMultiInstance(newEl, getTemplate(), getManager(),
					getParameterReference(), this);
		}
		if (inst != null) {
			children.add(inst);
		}
	}
	
	public AbstractInstance getItem(int index) {
		return children.get(index);
	}
	
	public void deleteItem(int index) {
		AbstractInstance ai = children.remove(index);
		Element e = ai.getElement();
		e.getParentNode().removeChild(e);
	}
	
	private void loadChildInstances() throws TemplateException {
		NodeList childInstancesNodeList = null;
		try {
			childInstancesNodeList = Utils.evaluateXPath(getElement(), "instance");
		} catch (XPathExpressionException e) {
			throw new TemplateException(e);
		}
		
		if (childInstancesNodeList == null)
			return;
		for (int i = 0; i < childInstancesNodeList.getLength(); i++) {
			Element el = (Element) childInstancesNodeList.item(i);
			AbstractInstance inst = null;
			if (getParameterReference().isValue()) {
				inst = InstanceFactory.newMultiInstance(el, getTemplate(), getManager(), getParameterReference(), this);
			} else if (getParameterReference().isLink() || getParameterReference().isReference()) {
				Template t = getManager().findTemplate(getParameterReference().getReference());
				inst = InstanceFactory.newMultiInstance(el, t, getManager(), getParameterReference(), this);
			}
			if (inst != null) {
				children.add(inst);
			}
		}
	}

}
